using System;
using System.Collections.Generic;
using System.Text;
using Barrage.Render;

namespace Barrage
{
    /// <summary>
    /// Base class for a Barrage Game
    /// </summary>
    public abstract class Game:IDisposable
    {
        /// <summary>
        /// Must be inherited. Gets the Section (creating it if necessary) with the specified id
        /// </summary>
        /// <param name="id">Section Id</param>
        /// <returns>A game section instance</returns>
        public abstract GameSection GetSection(int id);
        /// <summary>
        /// Sets the section that will be used the next frame to the section with the specified Id.
        /// </summary>
        public int NextGameSectionId { set { NextGameSection = GetSection(value); } }

        private GameSection currentGameSection = null;
        private GameSection nextGameSection = null;

        /// <summary>
        /// Gets the currently used game section
        /// </summary>
        public GameSection CurrentGameSection{get{return currentGameSection;}}
        /// <summary>
        /// Sets the game section that will be used in the next frame
        /// </summary>
        public GameSection NextGameSection { get { return nextGameSection; } set { nextGameSection = value; } }
        
        /// <summary>
        /// When finished, the game must set this value to true, and the engine will close the application
        /// </summary>
        protected bool finished = false;
        /// <summary>
        /// Tells if the game is considered finished and the engine should exit the application.
        /// </summary>
        public bool Finished { get { return finished; } }

        /// <summary>
        /// Gets the list of the render processes of the active section
        /// </summary>
        public List<RenderProcess> RenderProcesses { get { if (CurrentGameSection != null) return CurrentGameSection.RenderProcesses; return new List<RenderProcess>(); } }

        /// <summary>
        /// Base constructor
        /// </summary>
        public Game()
        {            
        }

        /// <summary>
        /// Updates the scenes of the active game section
        /// </summary>
        public void UpdateScenes()
        {
            if (CurrentGameSection!=null)
                CurrentGameSection.UpdateScenes();
        }

        /// <summary>
        /// Loads the specified section so next frame it will be used as the current section
        /// The section's InitSection() method will be called.
        /// </summary>
        /// <param name="section">GameSection to be loaded</param>
        protected void LoadSection(GameSection section)
        {
            LoadSection(section, true);
        }

        /// <summary>
        /// Loads the specified section so next frame it will be used as the current section
        /// </summary>
        /// <param name="section">GameSection to be loaded</param>
        /// <param name="initSection">Tells if the section's InitSection() method must be called or not</param>
        protected virtual void LoadSection(GameSection section, bool initSection)
        {
            currentGameSection = section;
            if (initSection)
                currentGameSection.InitSection();
        }

        /// <summary>
        /// Loads the section marked as next and unloads the current section.
        /// </summary>
        protected void ReloadSection()
        {
            if (CurrentGameSection != null)
                CurrentGameSection.Dispose();
            currentGameSection = nextGameSection;
            if (currentGameSection != null)
                currentGameSection.InitSection();
            nextGameSection = null;
            
        }

        /// <summary>
        /// Main game loop. Calls the active secton MainLoop and updates the next section if necessary
        /// </summary>
        public virtual void MainLoop()
        {
            CurrentGameSection.MainLoop();
            if (nextGameSection != null)
                ReloadSection();
        }

        /// <summary>
        /// Inits the game and sets the first section
        /// </summary>
        public abstract void InitGame();

        /// <summary>
        /// Free resources
        /// </summary>
        public virtual void Dispose()
        {
            if (currentGameSection != null)
                currentGameSection.Dispose();
            nextGameSection = null;
            currentGameSection = null;
            NLog.LogManager.GetLogger(ToString()).Debug("Disposing"); 
            GC.SuppressFinalize(this);            
        }

        /// <summary>
        /// Destructor. Free resources
        /// </summary>
        ~Game()
        {
            Dispose();
        }

    }
}
